﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;
using System.IO;
using System.Web;
using System.Web.Routing;
using System.Web.Mvc;
using Microsoft.Practices.Unity;
using Vit.Common;
using Vit.Common.Helpers;
using Vit.Common.Extensions;
using Vit.Common.Providers;
using Vit.Web.Fakes;
using Vit.Web.Modules;
using Vit.Web.Providers;
using Vit.Web.Models;
using Vit.Web.Extensions;
using Vit.Web.Mvc.Attributes;

namespace Vit.Web.Helpers
{
    public class PortalHelper
    {
        public static User CreateAnonymousUser()
        {
            User user = new User()
            {
                Name = "Anonymous",
                Account = string.Empty,
                Password = string.Empty,

                LastLoginTime = DateTime.MinValue,
                LastActiveTime = DateTime.Now,
                LastRequestUrl = HttpContext.Current.Request.RawUrl
            };

            user.Site = PortalContext.Current.Site;

            user.Profiles.Add(new Profile() { Name = "Theme", Value = "Default" });
            user.Profiles.Add(new Profile() { Name = "Skin", Value = "Default" });
            user.Profiles.Add(new Profile() { Name = "CultureInfo", Value = "zh-CN" });
            user.Profiles.Add(new Profile() { Name = "TimeZone", Value = "8" });
            user.Profiles.Add(new Profile() { Name = "MenuGroup", Value = "" });
            user.Profiles.Add(new Profile() { Name = "LogonUrl", Value = "/Admin/Index" });

            return user;
        }

        public static bool CanCurrentUserAccess(string permissionUri)
        {
            return Unity.Current.ResolveAny<IMembershipProvider>().ForEach<IMembershipProvider, bool>(p => p.CanUserAccess(PortalContext.Current.User.Account, permissionUri));
        }

        public static void RegisterWidgets(Assembly asm, string areaName = null)
        {
            Type controllerType = typeof(Controller);
            foreach (Type type in asm.GetTypes().Where(o => o.IsAbstract == false))
            {
                // register widgets
                if (controllerType.IsAssignableFrom(type))
                {
                    ReflectedControllerDescriptor cd = new ReflectedControllerDescriptor(type);
                    foreach (ActionDescriptor ad in cd.GetCanonicalActions())
                    {
                        WidgetAttribute wa = ad.GetCustomAttributes(typeof(WidgetAttribute), true).FirstOrDefault() as WidgetAttribute;
                        if (wa != null)
                        {
                            string widgetUrl = string.Format("{0}/{1}/{2}", string.IsNullOrEmpty(areaName) ? string.Empty : "/" + areaName, cd.ControllerName, ad.ActionName);
                            Widget widget = new Widget()
                            {
                                WidgetName = Locale.GetString("Widgets", widgetUrl),
                                Area = areaName,
                                Controller = cd.ControllerName,
                                Action = ad.ActionName,
                                DefaultParameters = wa.Parameters == null ? null : wa.Parameters.ToFormatString("&", "=", "", ""),
                            };

                            Unity.Current.RegisterInstance<Widget>(widget.WidgetName, widget);
                        }
                    }
                }
            }
        }

        public static IEnumerable<Widget> GetAllWidgets()
        {
            return Unity.Current.ResolveAny<Widget>();
        }

        public static string[] CacheDependency = new string[] { "WidgetsCacheDependency" };

        public static void ClearWidgetsCache()
        {
            ICacheProvider cache = Unity.Current.Resolve<ICacheProvider>();
            if (cache != null)
            {
                cache.RemoveDependencySet(CacheDependency);
            }
        }

        private static List<FileInfo> configurationFiles;
        public static List<FileInfo> ConfigurationFiles
        {
            get
            {
                if (configurationFiles == null)
                {
                    configurationFiles = new List<FileInfo>();
                    var server = HttpContext.Current.Server;
                    DirectoryInfo dir = new DirectoryInfo(server.MapPath("/Configuration"));
                    if (dir.Exists)
                    {
                        foreach (var f in dir.GetFiles("*.*", SearchOption.AllDirectories))
                        {
                            configurationFiles.Add(f);
                        }
                    }
                    dir = new DirectoryInfo(server.MapPath("/Areas"));
                    if (dir.Exists)
                    {
                        foreach (var d in dir.GetDirectories())
                        {
                            foreach (var cd in d.GetDirectories("Configuration", SearchOption.TopDirectoryOnly))
                            {
                                foreach (var f in cd.GetFiles("*.*", SearchOption.AllDirectories))
                                {
                                    configurationFiles.Add(f);
                                }
                            }
                        }
                    }
                }

                return configurationFiles;
            }
        }

        private static IEnumerable<Assembly> assemblies;
        public static IEnumerable<Assembly> Assemblies
        {
            get
            {
                if (assemblies == null)
                    assemblies = LoadAssemblies(HttpContext.Current);
                return assemblies;
            }
        }

        public static IEnumerable<Assembly> LoadAssemblies(HttpContext context)
        {
            List<Assembly> list = new List<Assembly>();
            DirectoryInfo dir = new DirectoryInfo(context.Server.MapPath("/bin"));
            foreach (var file in dir.GetFiles("*.dll"))
            {
                Assembly asm = Assembly.LoadFrom(file.FullName);
                list.Add(asm);
            }
            return list;
        }
    }
}
